#pragma once
#include <iostream>
#include <mutex>
#include <thread>
#include <queue>
#include <unistd.h>
#include <memory>
#include <functional>
#include <vector>
#include <condition_variable>
#include "Log.hpp"

namespace ThreadPoolModule
{
    const static int defaultnum = 5;

    using namespace LogModule;
    using thread_t = std::shared_ptr<std::thread>;

    void DefaultTest()
    {
        while (1)
        {
            sleep(1);
            LOG(LogLevel::DEBUG);
        }
    }
    template <typename T>
    class ThreadPool
    {
        bool IsEmpty()
        {
            return _taskq.empty();
        }
        void HanderTask()
        {
            LOG(LogLevel::DEBUG) << "线程进入Handertask逻辑";
            while (true)
            {
                // 拿任务
                T t;
                {
                    std::unique_lock<std::mutex> lock(_lock);
                    _wait_num++;
                    _cond.wait(lock, [this]
                               { return !IsEmpty(); });
                    _wait_num--;

                    if(IsEmpty()&& !_isrunning)
                        break;

                    t = _taskq.front();
                    _taskq.pop();
                }
                // 处理任务，规定用()方法
                t(int());
            }
            LOG(LogLevel::INFO)<<"线程:"<<pthread_self()<<"退出";
        }

        ThreadPool(const ThreadPool<T>&) = delete;
        ThreadPool<T>& operator=(const ThreadPool<T>&) = delete;
        ThreadPool(int num = defaultnum) : _num(num), _wait_num(0), _isrunning(false)
        {}
    public:
        static ThreadPool<T>* GetInstance()
        {
            if(instance == nullptr)
            {
                std::lock_guard<std::mutex> lock(_mutex);
                if(instance == nullptr)
                {
                    LOG(LogLevel::INFO)<<"单例首次被运行";
                    instance = new ThreadPool<T>();
                    instance->Start();
                }
            }
         
            return instance;
        }
        
        void Start()
        {
            if (_isrunning)
                return;
            for (int i = 0; i < _num; i++)
            {
                sleep(1);
                _threads.push_back(std::make_shared<std::thread>(std::bind(&ThreadPool::HanderTask, this)));
                LOG(LogLevel::INFO) << "创建线程" << _threads[i]->get_id() << "成功";
            }
            _isrunning = true;
        }
        void Equeue(T& in)
        {
            std::lock_guard<std::mutex> lock(_lock);
            _taskq.push(in);

            if (_wait_num > 0)
                _cond.notify_one();
        }
        void Join()
        {
            for (auto &thread_ptr : _threads)
            {
                thread_ptr->join();
                LOG(LogLevel::INFO) << "等待线程" << thread_ptr->get_id() << "成功";
            }
        }
        void Stop()
        {
            std::lock_guard<std::mutex> lock(_lock);
            if(_isrunning)
            {
                _isrunning = false;
                if(_wait_num>0)
                    _cond.notify_all();
            }
        }
        ~ThreadPool()
        {
        }

    private:
        int _num;
        std::queue<T> _taskq; // 任务列表
        std::vector<thread_t> _threads;
        std::mutex _lock;
        std::condition_variable _cond;
        int _wait_num;
        bool _isrunning;

        static ThreadPool<T>* instance;
        static std::mutex _mutex;
    };

    template<typename T>
    ThreadPool<T>* ThreadPool<T>::instance = nullptr;
    template<typename T>
    std::mutex ThreadPool<T>::_mutex;
}